package org.jeecg.modules.tenant;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.jdbc.ScriptRunner;
import org.jeecg.common.api.vo.Result;
import org.jeecg.modules.system.util.SakurUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.Base64;
import java.util.Date;

/**
 * @author sakur
 * @since 2022/11/16
 */
@RestController
@RequestMapping("/tenant")
public class TenantController {

    @Resource
    private Statement statement;

    @Resource
    private SakurUtils sakurUtils;

    /**
     * 添加租户
     * @param tenant 租户信息 {
     *               database: 库名 string,
     *               tenant_key: 租户key string,
     *               tenant_type: 数据库类型 int,
     *               username: 用户名 String,
     *               password: 密码 String,
     *               active: 租户状态 bool
     * }
     */
    @PostMapping("/addTenant")
    public Result<?> addTenant(@RequestBody JSONObject tenant) {
        String database = tenant.getString("database");
        boolean a = checkDatabaseExists(database);
        if (!a) return Result.error("database doesn't exists");
        String key = tenant.getString("tenant_key");
        key = key == null ? String.valueOf(new Date().getTime()/60000) : key;
        int type = StringUtils.isEmpty(tenant.getString("tenant_type")) ? 0 : tenant.getInteger("tenant_type");
        boolean active = StringUtils.isEmpty(tenant.getString("active")) || tenant.getBoolean("active");
        String u = StringUtils.isEmpty(tenant.getString("username")) ? sakurUtils.username : tenant.getString("username");
        String p = StringUtils.isEmpty(tenant.getString("password")) ? sakurUtils.password : tenant.getString("password");
        String url = sakurUtils.MySQL_url.replace("{database}", database);

        String sql = "insert into tenant_datasource.tenant_datasource(tenant_key, tenant_type, url, username, password, active) " +
                "values ('" + key + "', " + type + ", '" + url + "', '" + u + "', '" + p + "', " + active + ")";
        int r = 0;
        try {
            r += statement.executeUpdate(sql);
        } catch (SQLException e) {
            System.out.println("insert into tenant error");
        }
        return r > 0 ? Result.ok() : Result.error("insert zero record");
    }

    /**
     * 检查数据库是否被占用
     * @param database 数据库名称
     * @return true没占用, false占用
     */
    @GetMapping("/checkDatabaseState")
    public Result<?> checkDatabaseState(String database) {
        String sql = "select * from tenant_datasource.tenant_datasource";
        String msg;
        boolean a = true;
        try {
            ResultSet r = statement.executeQuery(sql);
            while (r.next()) {
                String url = r.getString("url");
                String []s = url.split("\\?");
                if (s[0].endsWith(database)) {
                    a = false;
                    break;
                }
            }
            r.close();
            msg = a ? "can use" : "the databse has been used";
        } catch (SQLException e) {
            a = false;
            msg = sql + "\nexecute error";
        }
        return a ? Result.ok(msg) : Result.error(msg);
    }

    /**
     * 检查key是否被占用
     * @param key 租户key
     * @return true没占用, false占用
     */
    @GetMapping("/checkKey")
    public Result<?> checkKey(String key) {
        String sql = "select * from tenant_datasource.tenant_datasource";
        String msg;
        boolean a = true;
        try {
            ResultSet r = statement.executeQuery(sql);
            while (r.next()) {
                String k = r.getString("tenant_key");
                if (k.equals(key)) {
                    a = false;
                    break;
                }
            }
            r.close();
            msg = a ? "can use" : "the key has been used";
        } catch (SQLException e) {
            a = false;
            msg = sql + "\nexecute error";
        }
        return a ? Result.ok(msg) : Result.error(msg);
    }

    /**
     * 更新租户状态
     * @param key tenant_key
     */
    @GetMapping("/updateAcitve")
    public Result<?> updateActive(String key, String active) {
        boolean a;
        if (active.equals("true")) a = true;
        else if (active.equals("false")) a = false;
        else return Result.error("no support active's value");
        String sql = "update tenant_datasource.tenant_datasource set active = " + a + " where tenant_key = '" + key + "'";
        try {
            a = statement.executeUpdate(sql) > 0;
        } catch (SQLException e) {
            System.out.println("更新租户状态失败");
        }
        return a ? Result.ok() : Result.error("invalid key");
    }

    /**
     * 删除租户
     * @param key tenant_key
     */
    @GetMapping("/deleteTenant")
    public Result<?> deleteTenant(String key) {
        boolean a;
        String sql = "delete from tenant_datasource.tenant_datasource where tenant_key = '" + key + "'";
        try {
            a = statement.executeUpdate(sql) > 0;
        } catch (SQLException e) {
            a = false;
        }
        return a ? Result.ok() : Result.error("invalid key");
    }

    @GetMapping("/getAll")
    public Result<?> getAll() {
        String sql = "select * from tenant_datasource.tenant_datasource";
        ResultSet r;
        JSONArray array = new JSONArray();
        try {
            r = statement.executeQuery(sql);
            array = SakurUtils.extractJSONArray(r);
            r.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return Result.ok(array);
    }

    /**
     * 修改租户
     * @param tenant 租户信息 {
     *               database: 库名 string,
     *               tenant_key: 租户key string,
     *               tenant_type: 数据库类型 int,
     *               username: 用户名
     *               password: 密码
     *               active: 租户状态 bool
     * }
     */
    @PostMapping("/editTenant")
    public Result<?> editTenant(@RequestBody JSONObject tenant) {
        String database = tenant.getString("database");
        boolean a = checkDatabaseExists(database);
        if (!a) return Result.error("database doesn't exists");
        String key = tenant.getString("tenant_key");
        int type = StringUtils.isEmpty(tenant.getString("tenant_type")) ? 0 : tenant.getInteger("tenant_type");
        boolean active = StringUtils.isEmpty(tenant.getString("active")) || tenant.getBoolean("active");
        String u = StringUtils.isEmpty(tenant.getString("username")) ? sakurUtils.username : tenant.getString("username");
        String p = StringUtils.isEmpty(tenant.getString("password")) ? sakurUtils.password : tenant.getString("password");
        String url = sakurUtils.MySQL_url.replace("{database}", database);

        String sql = "update tenant_datasource.tenant_datasource set " +
                "tenant_type = " + type + ", " +
                "url = '" + url + "', " +
                "username = '" + u + "', " +
                "password = '" + p + "', " +
                "active = " + active +
                " where tenant_key = '" + key + "'";
        int r = 0;
        try {
            r = statement.executeUpdate(sql);
        } catch (SQLException e) {
            System.out.println("insert into tenant error");
        }
        return r > 0 ? Result.ok(r) : Result.error("insert zero record");
    }

    //======= 下面是工具 =======
    public boolean checkDatabaseExists(String database) {
        String sql = "select * from information_schema.SCHEMATA";
        boolean a = false;
        try {
            ResultSet r = statement.executeQuery(sql);
            while (r.next()) {
                if (r.getString("SCHEMA_NAME").equals(database)) {
                    a = true;
                    break;
                }
            }
            r.close();
        } catch (SQLException e) {
            System.out.println(sql + "\nexecute error");
        }
        return a;
    }

    public static void main(String[] args) {
        String s = "ewoJInN1YmplY3QiOiAiZHVveXVhbiIsCgoJImlzc3VlZFRpbWUiOiAiMjAyMC0wNS0wMSAwODozMDowMCIsCgkiZXhwaXJ5VGltZSI6ICIyMDIzLTEyLTMxIDA4OjMwOjAwIiwKCSJkZXNjcmlwdGlvbiI6ICLns7vnu5/ova/ku7borrjlj6/or4HkuaYiLAoJImxpY2Vuc2VDaGVjayI6IHsKCQkiaXBBZGRyZXNzIjogIjE5Mi4xNjguMS4yIiwKCgoKCQkicmVnaXN0ZXJBbW91bnQiOiAyMDAwCgoJfX0=";
        Base64.Decoder decoder = Base64.getDecoder();
        System.out.println(new String(decoder.decode(s), StandardCharsets.UTF_8));
    }
}
